---
description: 如何维护更新日志
title: 如何维护更新日志
language: zh-CN
version: 0.3.0
---

:markdown
  # 如何维护更新日志

  ## 更新日志绝对不应该是git日志的堆砌物

  Version **#{current_page.metadata[:page][:version]}**

  ### 更新日志是什么？
  更新日志（Change Log）是一个由人工编辑，以时间为倒序的列表。
  这个列表记录所有版本的重大变动。


  <pre class="changelog">#{File.read("CHANGELOG.md")}</pre>

  ### 为何要提供更新日志？
  为了让用户和开发人员更好知道每一个版本有哪些区别。

  ### 为何我要在乎呢？
  因为归根结底软件是为人提供的。既然你不关心人，那么为何写软件呢？
  多少你还是要关心你的受众。

  本文档原作者和另外两个人的一个[播客][thechangelog]向大家介绍了，
  为何代码的管理者和开发者应该在乎更新日志。如果你有一小时时间和很好的英文听力本领，
  不妨听听。

  ### 怎么定义好的更新日志
  好问题！

  一个好的更新日志，一定满足：

  - 给人而不是机器写的。记住，要说人话。
  - 快速跳转到任意段。所以采用markdown格式
  - 一个版本对应一个章节。
  - 最新的版本在上，最老的在下面。
  - 所有日期采用'YYYY-MM-DD'这种规范。（例如北京奥运会的2008年8月8日是2008-08-08）这个是国际通用，任何语言
  都能理解的，并且还被[xkcd](https://xkcd.com/1179/)推荐呢！
  - 标出来是否遵守[语义化版本格式][semver]
  - 每一个软件的版本必须：
    - 标明日期（要用上面说过的规范）
    - 标明分类（采用英文）。规范如下：
      - 'Added' 添加的新功能
      - 'Changed' 功能变更
      - 'Deprecated' 不建议使用，未来会删掉
      - 'Removed' 之前不建议使用的功能，这次真的删掉了
      - 'Fixed' 改的bug
      - 'Security' 改的有关安全相关bug


  ### 怎么尽可能减少耗费的精力？
  永远在文档最上方提供一个'Unreleased' 未发布区域，来记录当前的变化。
  这样作有两大意义。

  - 大家可以看到接下来会有什么变化
  - 在发布时，只要把'Unreleased'改为当前版本号，然后再添加一个新的'Unreleased'就行了


  ### 吐槽环节到了
  请你一定要注意：

  - **把git日志扔到更新日志里。**看似有用，然并卵。
  - **不写'deprecations'就删功能。**不带这样坑队友的。
  - **采用各种不靠谱日期格式** 2012年12月12日，也就中国人能看懂了。

  如果你还有要吐槽的，欢迎留[issue][issues]或者直接PR


  ### 世界上不是有标准的更新日志格式吗？
  貌似GNU或者GNU NEWS还是提过些规范的，事实是它们太过简陋了。
  开发有那么多种情况，采用那样的规范，确实是不太合适的。

  这个项目提供的[规范][CHANGELOG]是作者本人希望能够成为世界规范的。
  作者不认为当前的标准足够好，而且作为一个社区，我们是有能力提供更棒的规范。
  如果你对这个规范有不满的地方，不要忘记还可以[吐槽][issues]呢。

  ### 更新日志文件名应该叫什么？

  我们的案例中给的名字就是最好的规范：`CHANGELOG.md`，注意大小写。

  像`HISTORY.txt`, `HISTORY.md`, `History.md`, `NEWS.txt`,
  `NEWS.md`, `News.txt`, `RELEASES.txt`, `RELEASE.md`, `releases.md`这么
  多文件名就太不统一了。

  只会让大家更难找到。

  ### 为何不直接记录`git log`?

  因为git日志一定是乱糟糟的。哪怕一个最理想的由完美的程序员开发和提交的，哪怕一个
  从不忘记每次提交全部文件，不写错别字，不忘记重构每一个部分，也无法保证git日志完美无瑕。
  况且git日志的核心在于记录代码的演化，而更新日志则是记录最重要的变更。

  就像注释之于代码，更新日志之于git日志。前者解释*为什么*，而后者说明*发生了什么*。


  ### 更新日志能机器识别吗？
  非常困难，因为有各种不同的文件格式和其它规范。

  [Vandamme][vandamme]是一个Ruby程序（由[Gemnasium][gemnasium]团队制作），可以解析
  好多种（但绝对不是全部）开源库的更新日志。

  ### 到底是CHANGELOG还是更新日志

  CHANGELOG是文件名，更新日志是常用说法。CHANGELOG采用大写是有历史根源的。就像很多类似的文件
  [`README`][README]， [`LICENSE`][LICENSE]，还有[`CONTRIBUTING`][CONTRIBUTING]。

  采用大写可以更加显著，毕竟这是项目很重要的元信息。就像[开源徽章][shields]。

  ### 那些后来撤下的版本怎么办？
  因为各种安全/重大bug原因被撤下的版本被标记'YANKED'。这些版本一般不出现在更新日志里，但作者建议他们出现。
  显示方式应该是：

  `## [0.0.5] - 2014-12-13 [YANKED]`

  `[YANKED]`采用大写更加显著，因为这个信息很重要。而采用方括号则容易被程序解析。

  ### 是否可以重写更新日志
  当然。哪怕已经上线了，也可以重新更新更新日志。有许多开源项目更新日志不够新，所以作者就会帮忙更新。

  另外，很有可能你忘记记录一个重大功能更新。所以这时候应该去重写更新日志。

  ### 如何贡献？
  本文档并不是**真理**。这只是原作者的个人建议，并且包括许多收集的例子。
  哪怕[本开源库][gh]提供一个[更新日志案例][CHANGELOG]，我刻意没有提供一个
  过于苛刻的规则列表（不像[语义化版本格式][semver]）。

  这是因为我希望通过社区达到统一观点，我认为中间讨论的过程与结果一样重要。

  所以[欢迎贡献][gh]。


  [CHANGELOG]: https://github.com/olivierlacan/keep-a-changelog/blob/master/CHANGELOG.md
  [CONTRIBUTING]: https://github.com/olivierlacan/keep-a-changelog/blob/master/CONTRIBUTING.md
  [LICENSE]: https://github.com/olivierlacan/keep-a-changelog/blob/master/LICENSE
  [README]: https://github.com/olivierlacan/keep-a-changelog/blob/master/README.md
  [gemnasium]: https://gemnasium.com/
  [gh]: https://github.com/olivierlacan/keep-a-changelog
  [issues]: https://github.com/olivierlacan/keep-a-changelog/issues
  [semver]: https://semver.org/lang/zh-CN/
  [shields]: https://shields.io/
  [thechangelog]: https://changelog.com/podcast/127
  [vandamme]: https://github.com/tech-angels/vandamme/
